/************************************************************************
*Description: Program for sequential execution of matrix multiplication	*
*Authors:	  Amber Dhavale, Chitrangda Potdar, Ronald Ngatuni			*
*Version:	  1.0														*
************************************************************************/

//Inclusion of header files
#include <iostream>
#include <time.h>
#include <omp.h>
#include <cstdlib>
 
using namespace std;

/********************************************
* Name: main()								*
* Description: Program execution starts here*
********************************************/
int main()
{
       //Declaration of variables
       int const rowA = 5000;
       int const columnA = 2000;
       int const rowB = 2000;
       int const columnB = 2500;
       int const rowC = 5000;
       int const columnC = 2500;
       double startTime,endTime = 0.00;

       //Declaration of matrix variables (pointers for dynamic allocation)
	   double **matrixA,**matrixB,**matrixC;
  
       //Allocating memory for Matrix A
       matrixA = new double*[rowA];
       for(int rowIndex = 0; rowIndex < rowA; rowIndex++)
              *(matrixA + rowIndex) = new double[columnA];

	   //Initializing Matrix A
	   srand(time(NULL));
       for(int rowIndex = 0; rowIndex < rowA; rowIndex++)
              for(int columnIndex = 0; columnIndex < columnA; columnIndex++)            
                     matrixA[rowIndex][columnIndex] = (rand() % 99 + 1)/10.0;  
 
       //Allocating memory for Matrix B
       matrixB = new double*[rowB];
       for(int rowIndex = 0; rowIndex < rowB; rowIndex++)
              *(matrixB + rowIndex) = new double[columnB];

	   //Initializing Matrix B
       for(int rowIndex = 0; rowIndex < rowB; rowIndex++)
              for(int columnIndex = 0; columnIndex < columnB; columnIndex++)
                     matrixB[rowIndex][columnIndex] = (rand() % 99 + 1)/10.0;      

	   //Allocating memory for Matrix C
       matrixC = new double*[rowC];
       for(int rowIndex = 0; rowIndex < rowC; rowIndex++)
              *(matrixC + rowIndex) = new double[columnC];

	   //Initializing Matrix C
       for(int rowIndex = 0; rowIndex < rowC; rowIndex++)
              for(int columnIndex = 0; columnIndex < columnC; columnIndex++)
              {                   
                     matrixC[rowIndex][columnIndex] = 0;
              }

	   //Start Time Noted
       startTime = omp_get_wtime();
	
	   //Matrix Multiplication Logic
       for(int i = 0; i < rowA; i++)
              for(int j = 0; j < columnB; j++)
				  for(int k = 0; k < columnA; k++)
                           matrixC[i][j] += matrixA[i][k] * matrixB[k][j];
       
	   //End Time Noted
	   endTime = omp_get_wtime();
       
	   //Display the time required
	   cout << "Total Time required = " << (endTime - startTime) << " seconds" << endl;
}
